#!/usr/bin/env python
# encoding: utf-8
import pandas as pd
from utils.time_utisl import *
from utils.common import *
from feature_set.base_feature import BaseFeature, RequstData


class AppUnBCateV1(BaseFeature):
    def __init__(self):
        super().__init__()
        self.apply_time = None
        self.country_abbr = None
        self.cate_list = None
        self.applist_data_df = None
        self.function_map = {
            'gen_appbcate_feature': self.gen_appbcate_feature
        }

    def load_conf(self):
        """
        load config file
        Returns:

        """
        pass

    def load_request(self, request_data: RequstData):
        """
        get request data and format feature input data
        Args:
            request_data: input detail data

        Returns:
            format sms_data calllog_data applist_data sos_data
        """
        self.apply_time = self.trans_str_to_time(request_data.apply_time)
        self.country_abbr = request_data.country_abbr
        self.cate_list = self.app_cate_info['cate'].unique()
        applist_data = request_data.data_sources.get('applist_data', [])
        applist_data_df = self.process_data(applist_data)
        self.applist_data_df = pd.merge(applist_data_df, self.app_cate_info, left_on='app_package', right_on='package_name', how='left')

    def process_app_name(self, app_name):
        app_name = app_name.lower()
        app_name = sp_string_replace(app_name)
        app_name = app_name.replace('\xa0', ' ')
        app_name = app_name.replace('\'s', '')
        return app_name

    def get_issystem_app(self, data):
        data['is_system_new'] = data["isSystem"]
        return data

    def trans_str_to_time(self, str_time):
        return datetime.strptime(str_time, "%Y-%m-%d %H:%M:%S")

    def process_data(self, applist_data):
        if applist_data:
            applist_data_df = pd.DataFrame(applist_data)
            applist_data_df = applist_data_df.drop_duplicates(subset='app_package', keep='first')
            applist_data_df = self.get_issystem_app(applist_data_df)
            applist_data_df['app_name'] = applist_data_df['app_name'].apply(self.process_app_name)
            applist_data_df['install_time'] = applist_data_df['fi_time'].apply(time_trans, args=(self.country_abbr,))
            applist_data_df['install_date'] = applist_data_df['install_time'].apply(lambda x: x.date())
            applist_data_df['update_time'] = applist_data_df['lu_time'].apply(time_trans, args=(self.country_abbr,))
            applist_data_df['update_date'] = applist_data_df['update_time'].apply(lambda x: x.date())
            applist_data_df['is_update'] = (applist_data_df['install_time'] != applist_data_df['update_time']).astype(int)
            applist_data_df['apply_install_interval_time'] = (pd.to_datetime(self.apply_time) - pd.to_datetime(applist_data_df['install_time'], errors='coerce')).dt.days
            applist_data_df['apply_update_interval_time'] = (pd.to_datetime(self.apply_time) - pd.to_datetime(applist_data_df['update_time'], errors='coerce')).dt.days
        else:
            applist_data_df = pd.DataFrame(columns=['app_name', 'app_package', 'is_system_new', 'install_time', 'install_date', 'update_time', 'update_date', 'is_update', 'apply_install_interval_time', 'apply_update_interval_time'])
            self.logger.info('输入数据applist_data结点为空')
        return applist_data_df

    def gen_appbcate_feature(self):
        feature_dict = {}
        self.__gen_appbcate_stage1_feature(self.applist_data_df, feature_dict)

        for key, value in feature_dict.items():
            feature_dict[key] = float(value) if not np.isnan(value) else -999.0
        return feature_dict

    def __gen_appbcate_stage1_feature(self, applist_data_df, feature_dict):
        day_list = [1, 3, 7, 15, 30, 60, 90, 180, np.inf]
        action_list = ['install', 'update']
        notsys_data = applist_data_df[applist_data_df['is_system_new'] == 0]
        for action in action_list:
            notsys_data = notsys_data.sort_values(by=f'{action}_time')
            for day in day_list:
                cut_data = notsys_data[(notsys_data[f'apply_{action}_interval_time'] >= 0) & (notsys_data[f'apply_{action}_interval_time'] <= day)]
                for cate in self.cate_list:
                    if cate == 'singleapp':
                        cut_catedata = cut_data[cut_data['cate'] == cate]
                        cut_catedata_app_set = set(cut_catedata['package_name'])
                        single_app_list=self.app_cate_info.loc[self.app_cate_info['cate']=='singleapp','package_name'].tolist()
                        for single_app in single_app_list:
                            if single_app in cut_catedata_app_set:
                                single_app_is_install = 1
                            else:
                                single_app_is_install = 0
                            feature_dict[f'{action}_{single_app.replace(".", "")}_isinstall_{day}d'] = single_app_is_install
                    else:
                        cut_catedata = cut_data[cut_data['cate'] == cate]
                        app_cnt = len(cut_catedata['app_package'])
                        app_cnt_ratio = divide(app_cnt,len(cut_data))
                        day_cnt = cut_catedata[f'{action}_date'].nunique()

                        feature_dict[f'{action}_{cate}_app_cnt_{day}d'] = app_cnt
                        feature_dict[f'{action}_{cate}_app_cnt_ratio_{day}d'] = app_cnt_ratio
                        feature_dict[f'{action}_{cate}_day_cnt_{day}d'] = day_cnt

                        cut_catedata_groupby_date = cut_catedata.groupby([f'{action}_date']).agg(app_cnt=('app_package', 'count')).reset_index()

                        if not cut_catedata_groupby_date.empty:
                            first_last_days_diff = (max(cut_catedata_groupby_date[f'{action}_date']) - min(cut_catedata_groupby_date[f'{action}_date'])).days
                            apply_last_days_diff = (self.apply_time.date() - max(cut_catedata_groupby_date[f'{action}_date'])).days
                            apply_first_days_diff = (self.apply_time.date() - min(cut_catedata_groupby_date[f'{action}_date'])).days
                        else:
                            first_last_days_diff = np.nan
                            apply_last_days_diff = np.nan
                            apply_first_days_diff = np.nan

                        feature_dict[f'{action}_first_last_days_diff_{day}d'] = first_last_days_diff
                        feature_dict[f'{action}_apply_last_days_diff_{day}d'] = apply_last_days_diff
                        feature_dict[f'{action}_apply_first_days_diff_{day}d'] = apply_first_days_diff
        return feature_dict
